package com.gree.framework.entity;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;

@Data
@NoArgsConstructor
public class CusUserDetails implements UserDetails,Serializable {
    private static final long serialVersionUID = 500L;
    private static final Log logger = LogFactory.getLog(CusUserDetails.class);

    private String token;
    private Long loginTime;
    private Long expireTime;
    private Long refreshTime;
    private String ipaddr;
    private String browser;
    private String os;
    private SysUser user;

    private String password;
    private String comp;
    private String compfield;
    private String username;

    private Set<GrantedAuthority> authorities;


    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;

    public CusUserDetails(String token, Long loginTime, Long expireTime,Long refreshTime, String ipaddr, String browser, String os, SysUser user,
                          String username, String password, String comp, String compfield, Collection<? extends GrantedAuthority> authorities) {
        this(token, loginTime, expireTime, refreshTime, ipaddr, browser, os, user,username, password,comp,compfield, true, true, true, true, authorities);
    }

    public CusUserDetails(String token, Long loginTime, Long expireTime,Long refreshTime, String ipaddr, String browser, String os, SysUser user,
                          String username, String password, String comp, String compfield, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        if (username != null && !"".equals(username) && password != null) {
            this.token = token;
            this.loginTime = loginTime;
            this.expireTime = expireTime;
            this.refreshTime = refreshTime;
            this.ipaddr = ipaddr;
            this.browser = browser;
            this.os = os;
            this.user = user;

            this.username = username;
            this.password = password;
            this.comp = comp;
            this.compfield = compfield;
            this.enabled = enabled;
            this.accountNonExpired = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        } else {
            throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
        }
    }

    public Collection<GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    public String getPassword() {
        return this.password;
    }

    public String getUsername() {
        return this.username;
    }

    public String getComp() {
        return this.comp;
    }

    public String getCompfield() {
        return this.compfield;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    public boolean isAccountNonExpired() {
        return this.accountNonExpired;
    }

    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }

    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }

    public void eraseCredentials() {
        this.password = null;
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet(new AuthorityComparator());
        Iterator var2 = authorities.iterator();

        while(var2.hasNext()) {
            GrantedAuthority grantedAuthority = (GrantedAuthority)var2.next();
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }

        return sortedAuthorities;
    }

    public boolean equals(Object rhs) {
        return rhs instanceof CusUserDetails ? this.username.equals(((CusUserDetails)rhs).username) : false;
    }

    public int hashCode() {
        return this.username.hashCode();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString()).append(": ");
        sb.append("Username: ").append(this.username).append("; ");
        sb.append("Password: [PROTECTED]; ");
        sb.append("Enabled: ").append(this.enabled).append("; ");
        sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
        sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
        sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
        if (!this.authorities.isEmpty()) {
            sb.append("Granted Authorities: ");
            boolean first = true;
            Iterator var3 = this.authorities.iterator();

            while(var3.hasNext()) {
                GrantedAuthority auth = (GrantedAuthority)var3.next();
                if (!first) {
                    sb.append(",");
                }

                first = false;
                sb.append(auth);
            }
        } else {
            sb.append("Not granted any authorities");
        }

        return sb.toString();
    }

    public static UserBuilder withUsername(String username) {
        return builder().username(username);
    }

    public static UserBuilder builder() {
        return new UserBuilder();
    }

    /** @deprecated */
    @Deprecated
    public static UserBuilder withDefaultPasswordEncoder() {
        logger.warn("CusUserDetails.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications.");
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        UserBuilder var10000 = builder();
        encoder.getClass();
        return var10000.passwordEncoder(encoder::encode);
    }

    public static UserBuilder withUserDetails(UserDetails userDetails) {
        return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled());
    }

    public static class UserBuilder {

        private String token;
        private Long loginTime;
        private Long expireTime;
        private Long refreshTime;
        private String ipaddr;
        private String browser;
        private String os;
        private SysUser user;

        private String username;
        private String password;
        private String comp;
        private String compfield;
        private List<GrantedAuthority> authorities;
        private boolean accountExpired;
        private boolean accountLocked;
        private boolean credentialsExpired;
        private boolean disabled;
        private Function<String, String> passwordEncoder;

        private UserBuilder() {
            this.passwordEncoder = (password) -> {
                return password;
            };
        }

        public UserBuilder token(String token) {
            Assert.notNull(token, "token cannot be null");
            this.token = token;
            return this;
        }

        public UserBuilder loginTime(Long loginTime) {
            Assert.notNull(loginTime, "loginTime cannot be null");
            this.loginTime = loginTime;
            return this;
        }

        public UserBuilder expireTime(Long expireTime) {
            Assert.notNull(expireTime, "expireTime cannot be null");
            this.expireTime = expireTime;
            return this;
        }

        public UserBuilder refreshTime(Long refreshTime) {
            Assert.notNull(refreshTime, "refreshTime cannot be null");
            this.refreshTime = refreshTime;
            return this;
        }

        public UserBuilder ipaddr(String ipaddr) {
            Assert.notNull(ipaddr, "ipaddr cannot be null");
            this.ipaddr = ipaddr;
            return this;
        }

        public UserBuilder browser(String browser) {
            Assert.notNull(browser, "browser cannot be null");
            this.browser = browser;
            return this;
        }

        public UserBuilder os(String os) {
            Assert.notNull(os, "os cannot be null");
            this.os = os;
            return this;
        }

        public UserBuilder user(SysUser user) {
            Assert.notNull(user, "user cannot be null");
            this.user = user;
            return this;
        }

        public UserBuilder username(String username) {
            Assert.notNull(username, "username cannot be null");
            this.username = username;
            return this;
        }

        public UserBuilder password(String password) {
            Assert.notNull(password, "password cannot be null");
            this.password = password;
            return this;
        }

        public UserBuilder comp(String comp) {
            Assert.notNull(comp, "comp cannot be null");
            this.comp = comp;
            return this;
        }

        public UserBuilder compfield(String compfield) {
            Assert.notNull(compfield, "compfield cannot be null");
            this.compfield = compfield;
            return this;
        }

        public UserBuilder passwordEncoder(Function<String, String> encoder) {
            Assert.notNull(encoder, "encoder cannot be null");
            this.passwordEncoder = encoder;
            return this;
        }

        public UserBuilder roles(String... roles) {
            List<GrantedAuthority> authorities = new ArrayList(roles.length);
            String[] var3 = roles;
            int var4 = roles.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String role = var3[var5];
                Assert.isTrue(!role.startsWith("ROLE_"), role + " cannot start with ROLE_ (it is automatically added)");
                authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
            }

            return this.authorities((Collection)authorities);
        }

        public UserBuilder authorities(GrantedAuthority... authorities) {
            return this.authorities((Collection)Arrays.asList(authorities));
        }

        public UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
            this.authorities = new ArrayList(authorities);
            return this;
        }

        public UserBuilder authorities(String... authorities) {
            return this.authorities((Collection) AuthorityUtils.createAuthorityList(authorities));
        }

        public UserBuilder accountExpired(boolean accountExpired) {
            this.accountExpired = accountExpired;
            return this;
        }

        public UserBuilder accountLocked(boolean accountLocked) {
            this.accountLocked = accountLocked;
            return this;
        }

        public UserBuilder credentialsExpired(boolean credentialsExpired) {
            this.credentialsExpired = credentialsExpired;
            return this;
        }

        public UserBuilder disabled(boolean disabled) {
            this.disabled = disabled;
            return this;
        }

        public CusUserDetails build() {
            String encodedPassword = (String)this.passwordEncoder.apply(this.password);
            return new CusUserDetails(this.token, this.loginTime, this.expireTime, this.refreshTime, this.ipaddr, this.browser, this.os,this.user, this.username, encodedPassword,this.comp, this.compfield ,!this.disabled, !this.accountExpired, !this.credentialsExpired, !this.accountLocked, this.authorities);
        }
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
        private static final long serialVersionUID = 500L;

        private AuthorityComparator() {
        }

        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            if (g2.getAuthority() == null) {
                return -1;
            } else {
                return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority());
            }
        }
    }
}
